﻿//-------------------------------------------------------------------
//	Copyright (c) 2010-2014  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_STL_Ext.h".
//-------------------------------------------------------------------

#ifndef _UXS_CL_PROGRAM_H
#define _UXS_CL_PROGRAM_H

#pragma once

#include "CLQueue.h"

namespace UX_STL
{
namespace CLShell
{

	//
	// Program Callback
	//

	class IProgramCallback
	{
	public:
		virtual void operator () (CLProgram *pProg) = 0;
	};


	//
	// CL Program
	//

	class UX_EXPORT CLProgram : public CLBaseObject
	{
		typedef void (CL_CALLBACK *POnProgramBuild)(cl_program program, void *user_data);

	protected:
		cl_program			_pID;
		IProgramCallback  *	_pCallback;
		bool				_bBuilded;
		
	protected:
		virtual void _RetainRef()	const;
		virtual void _ReleaseRef()	const;
		virtual uint _GetRefCount()	const;
		virtual void _Destroy();
		static void _s_GetOptions(cl_prog_options::type eOpt, uni_c_string sMacroses, string &sRes);
		static void CL_CALLBACK _s_OnBuild(cl_program program, void *user_data);

	public:
		CLProgram();
		~CLProgram();

		bool Create(const char *pSource);
		bool Create(const uni_array< const char *> &aSources);
		bool Create(const uni_array< string > &aSources);
		bool CreateBinary(const uni_array< uint8 > &aData);
		virtual void  Destroy();

		bool GetSource(OUT string &sSource) const;
		bool GetBinary(OUT binary_array_t &aData) const;
		bool GetBuildOptions(OUT string &sOptions) const;
		bool GetBuildLog(INOUT string &sLog) const;

		bool Build(cl_prog_options::type eOpt);
		bool Build(cl_prog_options::type eOpt, uni_c_string sMacroses);

		bool CreateKernels(array<CLKernel *> &aKernels) const;

		void SetCallback(IProgramCallback *pCB);

		cl_program	Id()		const	{ return _pID; }
		bool		IsBuilded()	const	{ return _bBuilded; }


		// Utils //
		static void s_Define(uni_c_string pDef, string &sRes);
		static void s_Define(uni_c_string pDef, uni_c_string pVal, string &sRes);
		static void s_Include(uni_c_string pDef, string &sRes);
	};




	inline void CLProgram::s_Define(uni_c_string pDef, string &sRes)
	{
		sRes << " -D " << pDef << ' ';
	}

	inline void CLProgram::s_Define(uni_c_string pDef, uni_c_string pVal, string &sRes)
	{
		sRes << " -D " << pDef << '=' << pVal << ' ';
	}

	inline void CLProgram::s_Include(uni_c_string pDef, string &sRes)
	{
		sRes << " -I " << pDef << ' ';
	}

//-------------------------------------------------------------------

}	// CLShell
}	// UX_STL

#endif	// _UXS_CL_PROGRAM_H